package cn.isjinhao.se.structure.impl;

import cn.isjinhao.se.structure.AbstractRetrieveSupported;
import cn.isjinhao.se.structure.KeySupported;
import cn.isjinhao.se.structure.StructureException;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @Author ISJINHAO
 * @Date 2021/7/6 22:21
 */
public class Tuple extends AbstractRetrieveSupported<Cell, Cell> implements KeySupported<Tuple> {

    private Table table;

    private TableMetaInfo tableMetaInfo = new TableMetaInfo();

    private List<Cell> cellList = new ArrayList<>();

    public Tuple() {
    }

    public Tuple(List<Cell> cellList) {
        if (cellList != null && !cellList.isEmpty()) {
            int i = 0;
            for (Cell cell : cellList) {
                insertItem(i, cell);
                i++;
            }
        }
    }

    public Tuple(Map<String, Object> valueMap) {
        if (valueMap == null) {
            throw new StructureException("无法使用 null 初始化 Record 对象。");
        }
        tableMetaInfo = new TableMetaInfo();
        Set<Map.Entry<String, Object>> entries = valueMap.entrySet();
        for (Map.Entry<String, Object> entry : entries) {
            String key = entry.getKey();
            Object value = entry.getValue();
            if (key == null || value == null) {
                throw new StructureException("Entry 为 null 时，无法初始化 Record 对象。");
            }
            ColumnMetaInfo columnMetaInfo = new ColumnMetaInfo(key, value.getClass());
            Cell cell = new Cell(columnMetaInfo, value);
            cellList.add(cell);
            tableMetaInfo.append(columnMetaInfo);
        }
    }

    @Override
    protected void insertItem(int index, Cell cell) {
        if (!checkIndexCanAdd(index)) {
            throw new StructureException("out of range, available range : [" + 0 + ", " + size() + "]");
        }
        if (cell == null && index == size()) {
            throw new StructureException("Tuple中追加的Cell不能为null！");
        }
        cellList.add(index, cell);
        tableMetaInfo.set(index, cell == null ? null : cell.getColumnMetaInfo());
    }

    @Override
    protected Cell removeItem(int index) {
        if (!checkIndexInRange(index)) {
            throw new StructureException("out of range, available range : [" + 0 + ", " + size() + ")");
        }
        tableMetaInfo.removeItem(index);
        return cellList.remove(index);
    }

    public TableMetaInfo getTableMetaInfo() {
        if (table != null) {
            return table.getTableMetaInfo();
        }
        return tableMetaInfo;
    }

    public void setTable(Table table) {
        this.table = table;
    }

    @Override
    public int size() {
        return cellList == null ? 0 : cellList.size();
    }

    @Override
    public Cell get(int index) {
        if (checkIndexInRange(index)) {
            return cellList.get(index);
        }
        return null;
    }

    @Override
    public Tuple key() {
        return this;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        cellList.forEach(item -> sb.append(item.mysqlToString()).append("\t\t"));
        return sb.toString();
    }

}
